package com.cskaoyan.javase.oop2._1extend._7fieldhidden;

/**
 * @description: 属性的隐藏
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 属性的隐藏: 当父子类中存在同名的属性时,直接访问该同名属性,会显示出子类的属性值
 *      但是这不是并不是被覆盖了,而是被隐藏了
 * 父子类中允许存在同名成员,创建子类对象,访问同名成员变量,会显示出子类的值
 *      我们可以通过getter方法,仍然去访问这个父类成员变量,所以属性不会被覆盖,而是隐藏
 *
 * 接下来,我们要研究对象名点访问成员变量的访问机制:
 *      目前对于继承中父子类,我们创建对象有以下方式:
 *          a,创建父类对象,然后用父类引用接收
 *          b,创建子类对象,然后用子类引用接收
 *          c,创建子类对象,然后用父类引用接收
 *      1,首先研究对象名点访问成员变量的访问范围(能够访问什么东西,在权限允许下)
 *          a,访问范围只限于父类中
 *          b,访问范围包括子类和父类
 *          c,访问范围限于父类
 *       以上,总结规律:
 *          对象名点访问成员变量的范围,和引用的数据类型有关,和对象无关
 *          如果引用是父类类型那么只能访问父类中存在的成员变量
 *          如果引用是子类类型,那么父子类成员变量都可以访问
 *
 * 对象名点访问成员变量,什么能够访问,什么不能访问是由编译器决定的,而变量的声明恰好是为了告诉编译器变量的数据类型
 *      所以ac变量都是Father类型,所以它们的访问范围是一致的
 * 对象名点访问成员变量,编译器存在如下检索机制:
 *      先从引用的数据类型中去找到该成员变量,如果找不到就先去父类中找,如果找到Object都找不到,那么就会报错
 *      所以: 在java代码编译阶段,子类是可以感受到父类的(子类是知道自己有爸爸的)
 *            但是父类是不知道它有子类(爸爸不知道自己还有儿子)
 *      2,对象名点访问成员变量的结果:
 *          a,访问结果是父类类型的
 *          b,访问结果是子类类型的
 *          c,访问结果是父类类型的
 *   以上,对象名点访问成员变量的结果也是根据引用的数据类型来决定的
 *
 * 总结:
 *     当我们使用对象名点访问成员变量时,
 *          它的访问范围,访问结果都是引用的数据类型来决定的,没有必要考虑具体的对象的类型
 *
 * 注意事项:
 *      1,父子类中同名属性是被隐藏了,可以通过父类有权限的getter方法访问父类同名成员
 *          还可以用super点去访问同名成员,需要注意的是它们都受访问权限限制
 *      2, 了解: 静态成员变量的同名情况
 *          相对独立,最好不考虑继承
 *
 */
public class Demo {
    public static void main(String[] args) {
        //创建子类对象
        /*Son s = new Son();
        System.out.println(s.a);
        System.out.println(s.getA());*/

        Father f = new Father();
        Son s = new Son();
        Father fs = new Son();
        System.out.println(f.a); //10
        System.out.println(s.a); //20
        System.out.println(fs.a); //10


    }
}

class Father {
    int a = 10;
    int fatherA = 100;

    //给出A的getter方法
    /*public int getA(){
        return a;
    }*/

}

class Son extends Father {
    int a = 20;
    int sonA = 200;
}
